/* 
 * Copyright 2013 Sébastien Mouquet.
 * 
 * This file is part of ECovoiturage.
 * 
 * ECovoiturage is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * ECovoiturage is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with ECovoiturage. If not, see http://www.gnu.org/licenses/.
 */
package com.smouquet.ecovoiturage.ui.page;

import com.smouquet.ecovoiturage.core.domain.Entreprise;
import com.smouquet.ecovoiturage.core.domain.Utilisateur;
import com.smouquet.ecovoiturage.ui.NotificationUtil;
import com.vaadin.data.Validator;
import com.vaadin.data.fieldgroup.FieldGroup;
import com.vaadin.data.fieldgroup.PropertyId;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.ui.AbstractSelect;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.PasswordField;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.util.ReflectTools;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.List;

/**
 * Formulaire de création d'un compte utilisateur.
 * 
 * @author sebastien.mouquet
 */
public class RegistrationForm extends VerticalLayout
                              implements Button.ClickListener
{
    private FormLayout layout;
    
    @PropertyId("nom")
    private TextField tfNom;
    @PropertyId("email")
    private TextField tfEmail;
    @PropertyId("mdp")
    private PasswordField pfMdp;
    @PropertyId("adresse")
    private TextField tfAdresse;
    @PropertyId("entreprise")
    private ComboBox cbEntreprise;
    
    private Button btnInscription;
    
    private FieldGroup fgForm;
    
    private List<Entreprise> entreprises;
    private Utilisateur utilisateur;
    
    
    public RegistrationForm()
    {
        layout();
    }
    
    public RegistrationForm(List<Entreprise> entreprises)
    {
        this.entreprises = entreprises;
        layout();
    }

    
    public void setEntreprises(List<Entreprise> entreprises)
    {
        this.entreprises = entreprises;
        
        if(cbEntreprise != null) {
            prepareAndInstallCbEntrepriseContainer();
        }
    }

    /**
     * @return L'utilisateur créé via le formulaire.
     */
    public Utilisateur getUtilisateur() {
        return utilisateur;
    }
    
    
    private void layout()
    {
        layout = new FormLayout();
        layout.setImmediate(true);
        
        tfNom = new TextField("Nom");
        tfNom.setWidth(300, Unit.PIXELS);
        tfNom.setImmediate(true);
        tfNom.setRequired(true);
        tfNom.setMaxLength(80);
        tfNom.setValidationVisible(true);
        tfNom.setNullRepresentation("");
        
        tfEmail = new TextField("Email");
        tfEmail.setWidth(300, Unit.PIXELS);
        tfEmail.setImmediate(true);
        tfEmail.setRequired(true);
        tfEmail.setMaxLength(100);
        tfEmail.setValidationVisible(true);
        tfEmail.setNullRepresentation("");
     
        pfMdp = new PasswordField("Mot de passe");
        pfMdp.setWidth(300, Unit.PIXELS);
        pfMdp.setImmediate(true);
        pfMdp.setRequired(true);
        pfMdp.setMaxLength(15);
        pfMdp.setValidationVisible(true);
        pfMdp.setNullRepresentation("");
        
        tfAdresse = new TextField("Adresse");
        tfAdresse.setWidth(300, Unit.PIXELS);
        tfAdresse.setImmediate(true);
        tfAdresse.setMaxLength(250);
        tfAdresse.setNullRepresentation("");
        
        cbEntreprise = new ComboBox("Entreprise");
        cbEntreprise.setWidth(300, Unit.PIXELS);
        cbEntreprise.setImmediate(true);
        cbEntreprise.setRequired(true);
        prepareAndInstallCbEntrepriseContainer();
        
        btnInscription = new Button("Créer le compte");
        btnInscription.addClickListener(this);
        
        layout.addComponent(tfNom);
        layout.addComponent(tfEmail);
        layout.addComponent(pfMdp);
        layout.addComponent(tfAdresse);
        layout.addComponent(cbEntreprise);
        layout.addComponent(btnInscription);
        
        addComponent(layout);
        
        utilisateur = new Utilisateur();
        fgForm = new FieldGroup(new BeanItem<Utilisateur>(utilisateur));
        fgForm.bindMemberFields(this);
        
        setSizeFull();
        setMargin(true);
        setComponentAlignment(layout, Alignment.MIDDLE_CENTER);
    }
    
    private void prepareAndInstallCbEntrepriseContainer()
    {
        BeanItemContainer<Entreprise> container = new BeanItemContainer<Entreprise>(Entreprise.class);

        for(Entreprise e : entreprises) {
            container.addItem(e);
        }
        
        cbEntreprise.setContainerDataSource(container);
        cbEntreprise.setItemCaptionMode(AbstractSelect.ItemCaptionMode.PROPERTY);
        cbEntreprise.setItemCaptionPropertyId("nom");
    }
    

    @Override
    public void buttonClick(ClickEvent event)
    {
        try
        {
            fgForm.commit();
            
            fireEvent(new CreateAccountEvent(this, utilisateur));
            
        } catch(Validator.InvalidValueException ex) {
            NotificationUtil.showWarningNotification("Formulaire incomplet et/ou données invalides");
        } catch(FieldGroup.CommitException ex) {
            NotificationUtil.showWarningNotification("Formulaire incomplet et/ou données invalides");
        }
    }
    
    
    public static class CreateAccountEvent extends Event
    {
        private Utilisateur utilisateur;
        
        public CreateAccountEvent(Component source, Utilisateur utilisateur) {
            super(source);
            this.utilisateur = utilisateur;
        }

        public Utilisateur getUtilisateur() {
            return utilisateur;
        }
    }
    
    public interface CreateAccountListener extends Serializable
    {
        public static final Method METHOD = ReflectTools.findMethod(CreateAccountListener.class, "onCreateAccount", CreateAccountEvent.class);
        
        void onCreateAccount(CreateAccountEvent event);
    }
    
    public void addCreateAccountListener(CreateAccountListener listener)
    {
        addListener(CreateAccountEvent.class, listener, CreateAccountListener.METHOD);
    }
    
    public void removeCreateAccountListener(CreateAccountListener listener)
    {
        addListener(CreateAccountEvent.class, listener, CreateAccountListener.METHOD);
    }
}
